package com.lcp.se.service;

import com.alibaba.fastjson.JSONObject;
import com.lcp.se.entity.data.AppletUser;
import com.lcp.se.entity.data.SubscribeMessageData;
import com.lcp.se.entity.data.VideoCall;
import com.lcp.se.mapper.AppletUserMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.Set;

/**
 * 推送消息
 * <p>
 * https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN
 *
 * @author lcp
 * @date 2020/8/21 9:55
 */
@Service
public class PushMessageService {
    private final Logger log = LoggerFactory.getLogger(AppletUserService.class);

    @Value("${mini-program.push-target-key-redis}")
    private String pushTargetKey;

    @Value("${mini-program.number-of-users-per-push}")
    private Long numberOfUsers;

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private AppletUserMapper appletUserMapper;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 推送订阅消息：视频通话提醒给志愿者，随机推送指定的数量(当可推送用户不大于指定数量时，则为全部推送)
     * 可以根据返回值判断是否推送成功（只要有一个志愿者推送成功则为成功）
     */
    public Boolean pushVideoCallMsg(VideoCall videoCall) {
        // 拼装请求地址
        String access_token = redisTemplate.opsForValue().get("access_token");
        String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + access_token;

        try {
            // 获取发起者昵称
            AppletUser appletUser = appletUserMapper.selectById(videoCall.getCreateUserOpenId());

            // TODO 推送算法待完善

            // 组装要推送数据
            JSONObject requestData = new JSONObject();
            // 以下是固定数据
            requestData.put("template_id", "V2N215C6c8dAg4qUxlZShk8VzxijNnRGUWop1BvB9Qo");
            requestData.put("page",
                    "/pages/volunteer/acceptcall/acceptcall?callId=" + videoCall.getId() + "&roomID=" + videoCall.getRoomId());
            requestData.put("miniprogram_state", "developer");
            JSONObject data = new JSONObject();
            // String.format("%tF %tT", date,date); 格式化时间
            data.put("date1", new SubscribeMessageData(
                    String.format("%tF %tT", videoCall.getCreateTime(), videoCall.getCreateTime())));
            data.put("name4", new SubscribeMessageData(appletUser.getNickName()));
            data.put("thing9", new SubscribeMessageData("一分钟内有效，请及时进入小程序接听或删除"));
            requestData.put("data", data);

            // requestData.put("touser", "oUO9X42Yapp0RkZpUKXGC0oBVD_4");

            // 随机取出的数量应该要 <= size，当 size >= 1 的时候
            long count = 1L;
            Long size = redisTemplate.opsForSet().size(pushTargetKey);
            if (Objects.isNull(size) || size == 0) {
                log.warn("暂无志愿者可以推送");
                return false;
            }
            log.info(size.toString());
            if (numberOfUsers > size && size >= 2) {
                count = size - 1;
            } else {
                count = numberOfUsers;
            }
            // distinctRandomMembers 不会取出重复数据
            Set<String> pushTarget = redisTemplate.opsForSet().distinctRandomMembers(pushTargetKey, count);

            int success = 0;
            for (String target : Objects.requireNonNull(pushTarget)) {
                // 设置推送用户的 openId
                requestData.put("touser", target);
                log.info("推送数据：" + requestData.toJSONString());
                String s = restTemplate.postForObject(url, requestData, String.class);
                JSONObject result = JSONObject.parseObject(s);
                if (result.getString("errcode").equals("0")) {
                    success++;
                    log.info("推送给志愿者：" + target + "成功");
                } else if (result.getString("errcode").equals("43101")) {
                    log.warn("推送给志愿者：" + target + "失败，原因：用户未订阅");
                    // 暂时剔除未订阅用户
                    redisTemplate.opsForSet().remove(pushTargetKey, target);
                }
            }
            return success > 0;
        } catch (Exception e) {
            log.info("推送出错：" + e.getMessage());
            return false;
        }
    }
}